package walls.service;

import ch.qos.logback.core.util.TimeUtil;
import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import walls.exception.VerificationException;

import java.time.Duration;
import java.time.LocalDate;
import java.util.concurrent.*;


@Service
public class EmailVerificationService {

    private final JavaMailSender mailSender;
    private final RedisTemplate<String, String> redisTemplate;

    @Value("${app.email.verification.code-length}")
    private int codeLength;

    @Value("${app.email.verification.expire-minutes}")
    private int expireMinutes;

    @Value("${app.email.verification.max-attempts}")
    private int maxAttempts;

    @Value("${app.email.verification.resend-cooldown}")
    private int resendCooldown;

    @Value("${app.email.verification.daily-limit}")
    private int dailyLimit;

    @Autowired
    public EmailVerificationService(JavaMailSender mailSender,
                                    RedisTemplate<String, String> redisTemplate) {
        this.mailSender = mailSender;
        this.redisTemplate = redisTemplate;
    }

    /**
     * 发送验证码邮件
     *
     * @param email 目标邮箱地址
     * @return 发送结果
     */
    public boolean sendVerificationCode(String email) {
        // 1. 检查冷却时间
//        if (isInCooldown(email)) {
//            throw new VerificationException("请等待" + resendCooldown + "秒后再试");
//        }

        // 2. 检查每日发送限制
//        String dailyKey = "verification:daily:" + LocalDate.now() + ":" + email;
//        Long dailyCount = redisTemplate.opsForValue().increment(dailyKey);
//        if (dailyCount != null && dailyCount > dailyLimit) {
//            throw new VerificationException("今日发送次数已达上限");
//        }
//        redisTemplate.expire(dailyKey, Duration.ofDays(1l) );

        // 3. 生成验证码
        String code = generateVerificationCode();

        // 4. 存储验证码到Redis
        String codeKey = "verification:code:" + email;
        redisTemplate.opsForValue().set(codeKey, code, Duration.ofMinutes(expireMinutes));

        // 5. 存储尝试次数计数器
        String attemptKey = "verification:attempts:" + email;
        redisTemplate.opsForValue().set(attemptKey, "0", Duration.ofMinutes(expireMinutes));

        // 6. 设置冷却时间
        String cooldownKey = "verification:cooldown:" + email;
        redisTemplate.opsForValue().set(cooldownKey, "1",Duration.ofMinutes(resendCooldown));

        // 7. 发送邮件
        sendStyledVerificationEmail(email, code);

        return true;
    }

    /**
     * 验证邮箱验证码
     *
     * @param email 邮箱地址
     * @param code 用户输入的验证码
     * @return 验证结果
     */
    public boolean verifyCode(String email, String code) {
        // 1. 获取存储的验证码
        String storedCode = redisTemplate.opsForValue().get("verification:code:" + email);
        if (storedCode == null) {
            throw new VerificationException("验证码已过期或不存在");
        }

        // 2. 检查尝试次数
        String attemptKey = "verification:attempts:" + email;
        Long attempts = redisTemplate.opsForValue().increment(attemptKey);
        if (attempts != null && attempts > maxAttempts) {
            // 超过最大尝试次数，删除验证码
            redisTemplate.delete("verification:code:" + email);
            throw new VerificationException("验证失败次数过多，请重新获取验证码");
        }

        // 3. 验证码比对
        if (storedCode.equals(code)) {
            // 验证成功，清除相关key
            redisTemplate.delete("verification:code:" + email);
            redisTemplate.delete(attemptKey);
            return true;
        }

        // 4. 验证失败
        int remaining = maxAttempts - attempts.intValue();
        throw new VerificationException("验证码错误，剩余尝试次数: " + remaining);
    }

    /**
     * 生成随机验证码
     */
    private String generateVerificationCode() {
        return RandomStringUtils.randomNumeric(codeLength);
    }

    /**
     * 发送简单验证码邮件
     */
    private void sendSimpleVerificationEmail(String email, String code) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setTo(email);
        message.setSubject("您的验证码");

        message.setText("<h1>您的验证码是: " + code + "</h1>\n\n"
                + "验证码将在 " + expireMinutes + " 分钟后过期。\n"
                + "请勿将此验证码分享给他人。\n\n"
                + "如果您没有请求此验证码，请忽略此邮件。");

        mailSender.send(message);
    }

    /**
     * 发送带样式的验证码邮件
     */
    public void sendStyledVerificationEmail(String email, String code) {
        try {
            MimeMessage mimeMessage = mailSender.createMimeMessage();
            MimeMessageHelper helper = null;
            try {
                helper = new MimeMessageHelper(mimeMessage, true, "UTF-8");
            } catch (MessagingException e) {
                throw new RuntimeException(e);
            }

            helper.setTo(email);
            helper.setSubject("您的验证码 - 请及时使用");

            // 创建带样式的HTML邮件
            String htmlContent = "<!DOCTYPE html>"
                    + "<html>"
                    + "<head>"
                    + "  <meta charset='UTF-8'>"
                    + "  <style>"
                    + "    body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }"
                    + "    .container { max-width: 600px; margin: 20px auto; padding: 20px; border: 1px solid #e0e0e0; border-radius: 8px; }"
                    + "    .code { font-size: 24px; font-weight: bold; color: #1a73e8; padding: 10px 0; }"
                    + "    .footer { margin-top: 30px; font-size: 12px; color: #777; text-align: center; }"
                    + "    .note { background-color: #f8f9fa; padding: 10px; border-radius: 4px; margin-top: 20px; }"
                    + "  </style>"
                    + "</head>"
                    + "<body>"
                    + "  <div class='container'>"
                    + "    <h2>验证码通知</h2>"
                    + "    <p>您的验证码是：</p>"
                    + "    <div class='code'>" + code + "</div>"
                    + "    <p>此验证码将在 <strong>" + expireMinutes + " 分钟</strong>后失效。</p>"
                    + "    <div class='note'>"
                    + "      <p>安全提示：</p>"
                    + "      <ul>"
                    + "        <li>请勿将验证码分享给他人</li>"
                    + "        <li>我们的工作人员不会向您索要验证码</li>"
                    + "        <li>如非本人操作，请忽略此邮件</li>"
                    + "      </ul>"
                    + "    </div>"
                    + "    <div class='footer'>"
                    + "      <p>本邮件由系统自动发送，请勿直接回复</p>"
//                    + "      <p>© " + java.time.Year.now().getValue() + " </p>"
                    + "    </div>"
                    + "  </div>"
                    + "</body>"
                    + "</html>";

            helper.setText(htmlContent, true);
            mailSender.send(mimeMessage);
        } catch (MessagingException e) {
//            handleEmailException(email, "验证码邮件", e);
        }
    }

    /**
     * 检查是否在冷却时间内
     */
    private boolean isInCooldown(String email) {
        String cooldownKey = "verification:cooldown:" + email;
        return redisTemplate.hasKey(cooldownKey);
    }

    /**
     * 获取剩余冷却时间
     */
    public long getRemainingCooldown(String email) {
        String cooldownKey = "verification:cooldown:" + email;
        Long ttl = redisTemplate.getExpire(cooldownKey,TimeUnit.SECONDS);
        return ttl != null ? ttl : 0;
    }
}